package com.example.lottery.service.impl;

import com.example.lottery.entity.DbBettingData;
import com.example.lottery.entity.DbOriginalData;
import com.example.lottery.enums.HttpCodeEnum;
import com.example.lottery.enums.ZodiacSignEnum;
import com.example.lottery.exception.BusinessException;
import com.example.lottery.req.OriginalDataRequest;
import com.example.lottery.res.BettingDataResponse;
import com.example.lottery.service.DataProcessingService;
import com.example.lottery.service.DbBettingDataService;
import com.example.lottery.service.DbOriginalDataService;
import com.example.lottery.util.ObjectUtils;
import com.example.lottery.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @title: DataProcessingServiceImpl
 * @projectName: lottery
 * @description:
 */
@Service
public class DataProcessingServiceImpl implements DataProcessingService {

    @Autowired
    DbBettingDataService dbBettingDataService;

    @Autowired
    DbOriginalDataService dbOriginalDataService;


    @Transactional
    @Override
    public void dataProcessing(OriginalDataRequest request) {
        String data = request.getOriginalData();
        DbOriginalData originalData = new DbOriginalData();
        originalData.setCreateDate(LocalDateTime.now());
        originalData.setDataValue(data);
        originalData.setCreateId("system");
        List<BettingDataResponse> list = washData(data);
        dbOriginalDataService.initializationData(originalData);
        dbBettingDataService.insertBettingData(list);
    }

    @Override
    public List<BettingDataResponse> findByBettingData() {
        List<DbBettingData> bettingData = dbBettingDataService.getBettingData();
        return ObjectUtils.buildBatch(BettingDataResponse.class, bettingData);
    }

    @Override
    public void resetData() {
        dbBettingDataService.deleteData();
    }


    private static List<BettingDataResponse> washData(String data) {
        List<BettingDataResponse> list = new ArrayList<>();
        String[] dataList = data.split("/");
        if (dataList.length == 2) {
            for (int i = 0; i < dataList.length; i++) {
                String value = dataList[i];
                InitializeData(value, list);
            }
        } else {
            InitializeData(data, list);
        }
        return list;
    }


    private static void InitializeData(String data, List<BettingDataResponse> list) {

        List<String> groupedByUnit = groupByUnit(data);

        for (String number : groupedByUnit) {
            String builData = replaceRule(number).trim();

            String[] dataList = splitByGeOrMai(builData);

            if (dataList.length != 2) {
                throw new BusinessException(HttpCodeEnum.BADREQUEST);
            }
            String betting = dataList[0].replaceAll("[\u4e00-\u9fa5]", "");
            String balance = dataList[1].replaceAll("[\u4e00-\u9fa5]", "");
            boolean b = noCompliance(betting, balance, list);
            if (!b) {
                semicolonEN(betting, balance, list);
            }
        }
    }


    /**
     * 按 元 / 米 分组解析字符串
     *
     * @param input 输入的投注字符串
     * @return Map<String, List < String>>  key=元/米, value=对应片段集合
     */
    public static List<String> groupByUnit(String input) {
        Pattern pattern = Pattern.compile(".*?[元米]");
        Matcher matcher = pattern.matcher(input);

        List<String> groups = new ArrayList<>();
        while (matcher.find()) {
            groups.add(matcher.group());
        }

        return groups;
    }


    /**
     * 无参数
     *
     * @param betting
     * @param balance
     * @param list
     */
    private static boolean noCompliance(String betting, String balance, List<BettingDataResponse> list) {
        if (isInteger(betting) && isInteger(balance)) {
            BettingDataResponse dataResponse = new BettingDataResponse();
            dataResponse.setBettingBalance(Integer.valueOf(balance));
            dataResponse.setBettingNumber(Integer.valueOf(betting));
            list.add(dataResponse);
            return true;
        }
        return false;
    }

    /**
     * 英文掉号
     *
     * @param betting
     * @param balance
     * @param list
     */
    private static void semicolonEN(String betting, String balance, List<BettingDataResponse> list) {
        String[] split = betting.split(",");
        String[] split1 = balance.split(",");
        if (split.length >= 1 && split1.length == 1) {
            for (String number : split) {
                if (StringUtils.isNotEmpty(number)) {
                    BettingDataResponse dataResponse = new BettingDataResponse();
                    dataResponse.setBettingBalance(Integer.valueOf(balance));
                    dataResponse.setBettingNumber(Integer.valueOf(number));
                    list.add(dataResponse);
                }
            }
        } else if (split.length >= 1 && split1.length >= 2) {
            for (String value : split1) {
                for (String number : split) {
                    if (StringUtils.isNotEmpty(number)) {
                        BettingDataResponse dataResponse = new BettingDataResponse();
                        dataResponse.setBettingBalance(Integer.valueOf(value));
                        dataResponse.setBettingNumber(Integer.valueOf(number));
                        list.add(dataResponse);
                    }
                }
            }
        } else {
            throw new BusinessException(HttpCodeEnum.BADREQUEST);
        }

    }


    public static boolean isInteger(String str) {
        try {
            Integer.parseInt(str);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }


    /**
     * 替换规则
     *
     * @param betting
     * @return
     */
    private static String replaceRule(String betting) {
        if (betting == null || betting.isEmpty()) {
            return betting;
        }

        // 1. 用正则一次性替换所有常见分隔符为空格
        betting = betting.replaceAll("[，,;；\\-。\\.\\+\\|、\\\\]", " ");

        // 2. 将多个空格压缩为一个空格
        betting = betting.replaceAll("\\s+", " ").trim();

        // 3. 再把空格替换为逗号
        betting = betting.replace(" ", ",");

        // 4. 替换生肖
        for (ZodiacSignEnum value : ZodiacSignEnum.values()) {
            betting = betting.replace(value.getCode(), value.getValue());
        }

        betting = removeTrailingChinese(betting);
        return betting;
    }


    private static String removeTrailingChinese(String text) {
        if (text == null || text.isEmpty()) {
            return text;
        }
        // 正则匹配结尾的一个或多个汉字并去掉
        return text.replaceAll("[\\u4e00-\\u9fa5]+$", "");
    }


    /**
     * 按“各”或“买”拆分字符串，如果包含“各”就按“各”，否则按“买”
     *
     * @param input 输入字符串
     * @return 拆分后的数组
     */
    public static String[] splitByGeOrMai(String input) {
        if (input == null || input.isEmpty()) {
            return new String[]{};
        }

        if (input.contains("各")) {
            return input.split("各");
        } else if (input.contains("买")) {
            return input.split("买");
        } else {
            return new String[]{input}; // 没有关键字，直接返回原字符串
        }
    }
}

